import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'dart:ui' as ui;
import 'package:flutter_svg/flutter_svg.dart' as svg;

import 'package:hixing_app/assets/r_img.dart';
import 'package:hixing_app/views/test_view/canvas_center_utils.dart';

import 'svg_info_model.dart';

class CanvasToCustom extends StatefulWidget {
  @override
  _CanvasToCustomState createState() => _CanvasToCustomState();
}

class _CanvasToCustomState extends State<CanvasToCustom> {
  ui.Image? imgData;
  List<SvgInfoModel> _svgList = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    SystemChrome.setPreferredOrientations(// 使设备横屏显示
        [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
    loadImg();
    loadSvg();
  }

//从文件读取svg文件，然后resize这个svg的尺寸，然后传入到custompaint绘制
  Future<void> loadSvg() async {
    // final _loader = svg.SvgPicture.asset(
    //   ImgR.imgBgPguinSVG,
    //   colorFilter: ColorFilter.mode(Colors.red, BlendMode.srcIn),
    // );
    // // final svg.PictureInfo pictureInfoGreyTest =
    //     await svg.vg.loadPicture(_loader, null);

    var svg1 = await rootBundle.loadString(ImgR.imgBgPguinSVG);

    final svg.PictureInfo pictureInfo1 = await svg.vg.loadPicture(
        svg.SvgStringLoader(
          svg1,
        ),
        null);
    var svg2 = await rootBundle.loadString(ImgR.imgBgMyFill);
    final svg.PictureInfo pictureInfo2 = await svg.vg.loadPicture(
        svg.SvgStringLoader(
          svg2,
        ),
        null);
    Size svg1NewSize = const Size(100, 100);
    SvgInfoModel svgInfo1 = SvgInfoModel(
        picture: pictureInfo1
            .picture /*resizeSvg(pictureInfo1.picture, pictureInfo1.size,
            newSize: svg1NewSize)*/
        ,
        size: pictureInfo1.size);

    Size svg2NewSize = const Size(50, 50);

    SvgInfoModel svgInfo2 = SvgInfoModel(
        picture: pictureInfo2
            .picture /*resizeSvg(pictureInfo2.picture, pictureInfo2.size,
            newSize: svg2NewSize)*/

        ,
        size: pictureInfo2.size);
    setState(() {
      _svgList.add(svgInfo1);
      _svgList.add(svgInfo2);
    });
  }

  ui.Picture resizeSvg(ui.Picture picture, Size oldSize,
      {Size newSize = const Size(100, 100)}) {
    final recorder = ui.PictureRecorder();
    final _canvas = Canvas(recorder);

    // Calculate scaling factors
    final scaleX = newSize.width / oldSize.width;
    final scaleY = newSize.height / oldSize.height;

    // Apply scale transform
    _canvas.scale(scaleX, scaleY);

    // Draw the original picture onto the new canvas
    _canvas.drawPicture(picture);

    // End recording and get the new Picture
    return recorder.endRecording();
  }

  Future<void> loadImg() async {
    var img = await loadImageFromAssets(ImgR.imgBgDog);
    setState(() {
      imgData = img;
    });
  }

  Future<ui.Image>? loadImageFromAssets(String path) async {
    ByteData data = await rootBundle.load(path);
    return decodeImageFromList(data.buffer.asUint8List());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        // appBar: AppBar(
        //   title: Text(
        //     'canvas绘制文字，图片，svg',
        //     style: TextStyle(fontSize: 18),
        //   ),
        // ),
        body: Stack(
      children: [
        Container(
          width: double.infinity,
          height: double.infinity,
          child: CustomPaint(
            painter: MyCustomPainter(img: imgData, svgList: _svgList),
          ),
        ),
        Positioned(
            top: 30,
            left: 30,
            child: Container(
              decoration: BoxDecoration(
                  color: Colors.black26,
                  borderRadius: BorderRadius.circular(40)),
              child: IconButton(
                onPressed: () {
                  Get.back();
                },
                icon: Icon(
                  Icons.arrow_back,
                  color: Colors.yellowAccent,
                  size: 30,
                ),
              ),
            ))
      ],
    ));
  }
}

class MyCustomPainter extends CustomPainter {
  MyCustomPainter({this.img, required this.svgList});

  ui.Image? img;
  List<SvgInfoModel> svgList;

  @override
  void paint(Canvas canvas, Size size) {
    print("调用paint方法 ========");
    // TODO: implement paint
    Paint _paint = Paint();

    canvas.translate(size.width / 2, size.height / 2);

    // 绘制坐标以及网格
    // _drawGrid(canvas, _paint, size);
    // _drawCoor(canvas, _paint, size);
    CanvasCenterUtils.drawGrid(canvas, _paint, size);
    CanvasCenterUtils.drawCoor(canvas, _paint, size);

    //绘制文字操作
    _drawTextTest(canvas, _paint);

    if (img != null) {
      //绘制图片操作
      _drawImgTest(canvas, _paint, img!);
    }
    if (svgList.isNotEmpty) {
      _drawSvgTest(canvas, _paint, svgList, size);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }
}

//绘制矢量图 svg
void _drawSvgTest(
    Canvas canvas, Paint paint, List<SvgInfoModel> svgList, Size size) {
  int resizeWidth = 50;
  int resizeHeight = 50;

  // 新建一个图层，然后使用colorFilter的着色器给画板上色，就可以绘制picture的颜色了
  canvas.saveLayer(null,
      Paint()..colorFilter = ColorFilter.mode(Colors.purple, BlendMode.srcIn));
  canvas.translate(-size.width / 2, 0);
  canvas.scale(resizeWidth / svgList[0].size.width,
      resizeHeight / svgList[0].size.height);
  canvas.drawPicture(svgList[0].picture);
  canvas.restore();

  // 新建一个图层，然后使用colorFilter的着色器给画板上色，就可以绘制picture的颜色了
  canvas.saveLayer(null,
      Paint()..colorFilter = ColorFilter.mode(Colors.red, BlendMode.srcIn));
  canvas.translate(size.width / 2 - resizeWidth, 0);
  canvas.scale(resizeWidth / svgList[1].size.width,
      resizeHeight / svgList[1].size.height);
  canvas.drawPicture(svgList[1].picture);
  canvas.restore();
}

// 绘制图片方法
void _drawImgTest(Canvas canvas, Paint paint, ui.Image img) {
  // 画笔设置透明度，会影响图片绘制的透明度
  // paint.color = Colors.black.withAlpha(100);
  paint.color = Colors.black;
  // 直接画 是图片的原尺寸
  // canvas.drawImage(img, Offset(-img.width / 2, -img.height / 2), paint);

  // 通过缩放的方式会绘制图片
  resizeImg(canvas, Size(100, 100), img, paint);
}

// 根据size 缩放图片
void resizeImg(Canvas canvas, Size size, ui.Image img, Paint paint,
    {double x = 0, double y = 0}) {
  double cmpWidth = 0;
  double cmpHeight = 0;
  if (img.width > img.height) {
    cmpHeight = (size.width / img.width) * img.height;
  } else if (img.width < img.height) {
    cmpWidth = (size.height / img.height) * img.width;
  }
  double renderWidth = cmpWidth == 0 ? size.width : cmpWidth;
  double renderHeight = cmpHeight == 0 ? size.height : cmpHeight;

  // Draw image with scaled width
  canvas.drawImageRect(
    img,
    Rect.fromLTRB(0, 0, img.width.toDouble(), img.height.toDouble()),
    // 如果要居中，就调这里的 x，y值
    Rect.fromLTRB(x, -renderHeight, renderWidth, 0),
    Paint(),
  );

  //drawImageRect中主要是两个矩形域，src 和 dst。
  // src 表示从资源图片 image 上抠出一块矩形域，所以原点是图片的左上角。
  // dst 表示将抠出的图片填充到画布的哪个矩形域中，所以原点是画布原点。
  canvas.drawImageRect(
    img,
    Rect.fromLTRB(0, 0, img.width.toDouble(), img.height.toDouble()),
    // 如果要居中，就调这里的 x，y值
    Rect.fromLTRB(x, -renderHeight, renderWidth, 0),
    Paint(),
  );

  //drawImageNine 中主要是两个矩形域，center 和 dst。
  // center 表示从资源图片image上一块可缩放的矩形域，所以原点是图片的左上角。
  // dst 表示将抠出的图片填充到画布的哪个矩形域中，所以原点是画布原点。
  // 这样很容易画出气泡的效果，即指定区域进行缩放，其余不动。
  // 就是 固定原来的尺寸，然后传入要裁剪的图片的矩形域
  // 绘制九宫格图片操作
  final Rect targetRect = Rect.fromLTWH(0, 0, size.width, size.height);
  final Rect centerSlice =
      Rect.fromLTWH(10, 10, renderWidth - 40, renderHeight - 20);
  canvas.drawImageNine(img, centerSlice, targetRect, Paint());
  // canvas.drawImageNine(
  //     img!,
  //     Rect.fromCenter(center: Offset(50, 50), width: 100, height: 50),
  //     Rect.fromCenter(
  //         center: Offset(
  //           -100,
  //           100,
  //         ),
  //         width: 150,
  //         height: 150),
  //     paint);
}

// 绘制文字方法
void _drawTextTest(Canvas canvas, Paint paint) {
  // 使用 ParagraphBuilder绘制文字
  _drawTextWithParagraph(canvas, TextAlign.center, paint);
  // 使用 TextPainter绘制
  _drawText(canvas, TextAlign.center, paint);

  // 往下位置60 再绘制一次填充颜色的
  canvas.save();
  canvas.translate(0, 60);
  _drawText(canvas, TextAlign.center, paint, color: Colors.green);
  canvas.restore();
}

void _drawText(Canvas canvas, TextAlign textAlign, Paint paint,
    {Color? color}) {
  Paint textPaint = Paint()
    ..style = PaintingStyle.stroke
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 1;
  TextPainter textPainter = TextPainter(
      text: TextSpan(
        text: "嗨兴科技111111",
        style: TextStyle(
            color: color,
            fontSize: 40,
            foreground: color == null ? textPaint : null),
      ),
      textDirection: TextDirection.rtl,
      textAlign: textAlign);
  textPainter.layout(); // 进行布局
  //获取size需要在layout之后
  Size _textSize = textPainter.size;
  canvas.drawRect(
      Rect.fromLTRB(-_textSize.width / 2, -_textSize.height / 2,
          _textSize.width / 2, _textSize.height / 2),
      paint..color = Colors.red.withAlpha(120));
  // 获取text的size尺寸，然后除于二
  textPainter.paint(
      canvas, Offset(-_textSize.width / 2, -_textSize.height / 2));
}

void _drawTextWithParagraph(Canvas canvas, TextAlign textAlign, Paint paint) {
  var builder = ui.ParagraphBuilder(ui.ParagraphStyle(
      // 构造文字盒子样式
      textAlign: textAlign,
      textDirection: TextDirection.ltr,
      maxLines: 1,
      fontSize: 40,
      fontWeight: FontWeight.normal
      // 添加text样式
      ))
    ..pushStyle(
      ui.TextStyle(
        color: Colors.red,
        //
        // textBaseline: ui.TextBaseline.ideographic,
      ),
    )
    // 添加文案
    ..addText("嗨兴科技");
  // 调用build 构建方法
  ui.Paragraph paragraph = builder.build();
  // 构建宽度区域
  paragraph.layout(ui.ParagraphConstraints(width: 300));
  canvas.drawParagraph(paragraph, Offset(0, 0));
  canvas.drawRect(
      Rect.fromLTRB(0, 0, 300, 40),
      paint
        ..color = Colors.blue.withAlpha(100)
        ..style = PaintingStyle.fill);
}

void _drawCoor(Canvas canvas, Paint _paint, Size size) {
  _paint
    ..color = Colors.blue
    ..strokeWidth = 2;
  Offset yEndPoint = Offset(0, size.height / 2);
  canvas.drawLine(Offset(0, -size.height / 2), yEndPoint, _paint);

  canvas.drawLine(yEndPoint, Offset(-10, size.height / 2 - 10), _paint);
  canvas.drawLine(yEndPoint, Offset(10, size.height / 2 - 10), _paint);

  Offset xEndPoint = Offset(size.width / 2, 0);
  canvas.drawLine(Offset(-size.width / 2, 0), xEndPoint, _paint);
  canvas.drawLine(xEndPoint, Offset(size.width / 2 - 10, -10), _paint);
  canvas.drawLine(xEndPoint, Offset(size.width / 2 - 10, 10), _paint);
}

_drawGrid(Canvas canvas, Paint paint, Size size) {
  // 绘制四分之一的网格 ,要画全屏的画需要用镜像的方法
  //如果是相同或者对称的对象，可以通过缩放进行对称变化。
  // 沿x轴镜像，就相当于canvas.scale(1, -1)；
  // 沿y轴镜像，就相当于canvas.scale(-1, 1)；
  // 沿原点镜像，就相当于canvas.scale(-1, -1)；
  _drawHalfGrid(canvas, paint, size);
  // x轴镜像
  canvas.save();
  canvas.scale(1, -1);
  _drawHalfGrid(canvas, paint, size);
  canvas.restore();
  // y轴镜像
  canvas.save();
  canvas.scale(-1, 1);
  _drawHalfGrid(canvas, paint, size);
  canvas.restore();
  // 原点镜像
  canvas.save();
  canvas.scale(-1, -1);
  _drawHalfGrid(canvas, paint, size);
  // canvas.drawLine(Offset(0, 0), Offset(100, 100), paint);
  canvas.restore();
}

_drawHalfGrid(Canvas canvas, Paint paint, Size size) {
  // 画网格
  double step = 20;
  paint
    ..color = Colors.grey
    ..strokeWidth = 1
    ..style = PaintingStyle.stroke;

  // 绘制横线
  canvas.save();
  // 计算绘制的 1/4 屏幕能画多少条线，然后循环就可以了
  for (int i = 0; i < size.height / 2 / step; i++) {
    canvas.drawLine(Offset(0, 0), Offset(size.width / 2, 0), paint);
    canvas.translate(0, step);
  }
  canvas.restore();
  // 绘制竖线
  canvas.save();
  // 计算绘制的 1/4 屏幕能画多少条线，然后循环就可以了
  for (int i = 0; i < size.width / 2 / step; i++) {
    canvas.drawLine(Offset(0, 0), Offset(0, size.height / 2), paint);
    canvas.translate(step, 0);
  }
  canvas.restore();
}
